package cn.wen.core.refresh;

import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.support.annotation.Nullable;
import android.support.v7.widget.RecyclerView;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;

import cn.wen.core.refresh.creator.LoadViewCreator;
import cn.wen.core.refresh.creator.RefreshHelper;


/**
 * Description: 下拉刷新上拉加载更多的RecyclerView
 */
public class XRecyclerView extends RefreshRecyclerView {
    // 上拉加载更多的辅助类
    private LoadViewCreator mLoadCreator;
    // 上拉加载更多头部的高度
    private int mLoadViewHeight = 0;
    // 上拉加载更多的头部View
    private View mLoadView;
    // 手指按下的Y位置
    private int mFingerDownY;
    // 当前是否正在拖动
    private boolean mCurrentDrag = false;
    // 当前的状态
    private int mCurrentLoadStatus;
    // 默认状态
    public int LOAD_STATUS_NORMAL = 0x00111;
    // 上拉加载更多状态
    public static int LOAD_STATUS_PULL_DOWN_REFRESH = 0x00222;
    // 松开加载更多状态
    public static int LOAD_STATUS_LOOSEN_LOADING = 0x00333;
    // 正在加载更多状态
    public int LOAD_STATUS_LOADING = 0x00444;
    // 是否还能加载更多
    private boolean enableLoadMore = false;
    // 加载更多View的高度
    private int mTempHeight;
    /**
     * 是否自动加载更多
     */
    private boolean isAutoLoadMore;


    public XRecyclerView(Context context) {
        this(context, null);
    }

    public XRecyclerView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public XRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        // 滚动监听--》》自动加载更多
        addOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                super.onScrollStateChanged(recyclerView, newState);
                if (!isAutoLoadMore||mLoadView==null) {
                    return;
                }
                if (newState == SCROLL_STATE_IDLE) {
                    if (mLoadCreator != null) {
                        mLoadViewHeight = mLoadView.getMeasuredHeight();
                        if (mLoadViewHeight > 0) {
                            mTempHeight = mLoadViewHeight;
                        }
                    }
                    // 如果是在最底部才处理，否则不需要处理
                    if (canScrollDown() || mCurrentLoadStatus == LOAD_STATUS_LOADING
                            || mLoadCreator == null || mLoadView == null || isRefreshing()) {
                        // 如果没有到达最顶端，也就是说还可以向上滚动就什么都不处理
                        return;
                    }
                    mCurrentLoadStatus = LOAD_STATUS_LOADING;
                    if (mLoadCreator != null) {
                        mLoadCreator.onLoading();
                    }
                    if (mListener != null) {
                        mListener.onLoading();
                    }
                }
            }
        });
    }

    // 先处理上拉加载更多，同时考虑加载列表的不同风格样式，确保这个项目还是下一个项目都能用
    // 所以我们不能直接添加View，需要利用辅助类
    public void addLoadViewCreator(LoadViewCreator loadCreator) {
        this.mLoadCreator = loadCreator;
        addRefreshView();

    }

    @Override
    public void setAdapter(RecyclerView.Adapter adapter) {
        super.setAdapter(adapter);
        addRefreshView();
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                // 记录手指按下的位置 ,之所以写在dispatchTouchEvent那是因为如果我们处理了条目点击事件，
                // 那么就不会进入onTouchEvent里面，所以只能在这里获取
                mFingerDownY = (int) ev.getRawY();
                break;

            case MotionEvent.ACTION_UP:
                if (mCurrentDrag) {
                    restoreLoadView();
                }
                break;
        }
        return super.dispatchTouchEvent(ev);
    }

    /**
     * 重置当前加载更多状态
     */
    private void restoreLoadView() {
        if (mCurrentLoadStatus == LOAD_STATUS_LOOSEN_LOADING) {
            mCurrentLoadStatus = LOAD_STATUS_LOADING;
            if (mLoadCreator != null) {
                mLoadCreator.onLoading();
            }
            if (mListener != null) {
                post(new Runnable() {
                    @Override
                    public void run() {
                        mListener.onLoading();
                    }
                });
            }
        }
        mCurrentDrag = false;
        if (mLoadView == null) {
            return;
        }
        int currentBottomMargin = ((ViewGroup.MarginLayoutParams) mLoadView.getLayoutParams()).bottomMargin;
        int finalBottomMargin = 0;
        int distance = currentBottomMargin - finalBottomMargin;

        // 回弹到指定位置
        ValueAnimator animator = ObjectAnimator
                .ofFloat(currentBottomMargin, finalBottomMargin)
                .setDuration(distance);
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float currentTopMargin = (float) animation.getAnimatedValue();
                setLoadViewMarginBottom((int) currentTopMargin);
            }
        });
        animator.start();
        mCurrentDrag = false;
    }


    @Override
    public boolean onTouchEvent(MotionEvent e) {
        switch (e.getAction()) {
            case MotionEvent.ACTION_MOVE:
                // 如果是在最底部才处理，否则不需要处理
                if (canScrollDown() || mCurrentLoadStatus == LOAD_STATUS_LOADING
                        || mLoadCreator == null || mLoadView == null || isRefreshing()) {
                    // 如果没有到达最顶端，也就是说还可以向上滚动就什么都不处理
                    return super.onTouchEvent(e);
                }
                // 解决上拉加载更多自动滚动问题
                if (mCurrentDrag) {
                    scrollToPosition(getAdapter().getItemCount() - 1);
                }
                // 获取手指触摸拖拽的距离
                int distanceY = (int) ((e.getRawY() - mFingerDownY) * mDragIndex);
                // 如果是已经到达头部，并且不断的向下拉，那么不断的改变refreshView的marginTop的值
                if (distanceY < 0) {
                    setLoadViewMarginBottom(-distanceY);
                    updateLoadStatus(-distanceY);
                    mCurrentDrag = true;
                    return true;
                }
                break;
        }

        return super.onTouchEvent(e);
    }

    /**
     * 更新加载的状态
     */
    private void updateLoadStatus(int distanceY) {
        if (distanceY <= 0) {
            mCurrentLoadStatus = LOAD_STATUS_NORMAL;
        } else if (distanceY < mLoadViewHeight / 3) {
            mCurrentLoadStatus = LOAD_STATUS_PULL_DOWN_REFRESH;
        } else {
            mCurrentLoadStatus = LOAD_STATUS_LOOSEN_LOADING;
        }

        if (mLoadCreator != null) {
            mLoadCreator.onPull(distanceY, mLoadViewHeight, mCurrentLoadStatus);
        }
    }

    /**
     * 添加底部加载更多View
     */
    private void addRefreshView() {
        if (enableLoadMore) {
            if (mLoadView != null) {
                return;
            }
            RecyclerView.Adapter adapter = getAdapter();
            if (adapter != null && mLoadCreator != null) {
                // 添加底部加载更多View
                View mFooterView = mLoadCreator.getLoadView(getContext(), this);
                if (mFooterView != null) {
                    addFooterView(mFooterView);
                    this.mLoadView = mFooterView;
                }
            }
        } else {
            if (mLoadView != null) {
                removeFooterView(mLoadView);
                mLoadView = null;
            }
        }

    }

    /**
     * 设置加载View的marginBottom
     */
    public void setLoadViewMarginBottom(int marginBottom) {
        ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) mLoadView.getLayoutParams();
        if (marginBottom < 0) {
            marginBottom = 0;
        }
        params.bottomMargin = marginBottom;
        mLoadView.setLayoutParams(params);
    }


    /**
     * @return Whether it is possible for the child view of this layout to
     * scroll up. Override this if the child view is a custom view.
     * 判断是不是滚动到了最顶部，这个是从SwipeRefreshLayout里面copy过来的源代码
     */
    public boolean canScrollDown() {
        if (!enableLoadMore) {
            return true;
        }
        return canScrollVertically(1);
    }

    /**
     * 停止加载更多
     */
    public void stopLoad() {
        mCurrentLoadStatus = LOAD_STATUS_NORMAL;
        restoreLoadView();
        if (mLoadCreator != null) {
            mLoadCreator.onStopLoad();
        }
    }

    // 处理加载更多回调监听
    private OnLoadMoreListener mListener;

    public void setOnLoadMoreListener(OnLoadMoreListener listener) {
        this.mListener = listener;
    }

    /**
     * 设置是否能够加载更多
     */
    public void setEnableLoadMore(boolean enableLoadMore) {
        this.enableLoadMore = enableLoadMore;
        if (mLoadCreator != null) {
            mLoadCreator.onStopEnable(enableLoadMore);
        }
        addRefreshView();

    }


    public interface OnLoadMoreListener {
        void onLoading();
    }

    @Override
    protected boolean isLoadMore() {
        return LOAD_STATUS_LOADING == mCurrentLoadStatus;
    }

    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
        // 添加刷新的头和加载更多脚
        RefreshHelper.addRefreshAndLoadMore(this);
    }

    /**
     * 设置自动是否自动加载更多
     */
    public void setAutoLoadMore(boolean autoLoadMore) {
        isAutoLoadMore = autoLoadMore;
    }
}
